"""
Copyright 2012 Wieser Dietmar, Margit Mutschlechner.

This file is part of Multimedia Social Networking Platform.

Multimedia Social Networking Platform is free software: 
you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Multimedia Social Networking Platform is distributed
in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Multimedia Social Networking Platform.  
If not, see <http://www.gnu.org/licenses/>.

"""

import unittest
import time
from msnp.persistence import PersistenceController
from msnp.model.PTPModel import User, Group, BackupContent, UserGroup
from msnp.model import PTPModel
from msnp.service.network.model import CustodyModel
from msnp.service.network.model.CustodyModel import MemberStatusChangedMessage
from msnp.service import utils




class PTPTest(unittest.TestCase):
    """Class to test the correctness of the PTP-database accessors"""
    
    __username1 = "testuser1"
    __username2 = "testuser2"
    __pw = "pw"
    __groupname = "testgroup"
    __ownername = __username1
    __description = "testDescr"
    __genre = "testGenre"
    __isActive = True
    __membername = __username2
    __memberstatus = PTPModel.MemberStatus.NOT_CONFIRMED
    __timestamp = utils.DateFormatter.formatTimeAsFloat()
    
#    __sendMessage = SendMessage(__username1, "hello", __membername)
    __memberStatusChangedMessage = MemberStatusChangedMessage(__username1, __username1, __groupname, __ownername, PTPModel.MemberStatusChangedReturnType.SUCCESSFUL, PTPModel.MemberStatus.NOT_CONFIRMED, True)
    __user1 = User(__username1, None, "pw", 0)
    __user2 = User(__username2, None, "pw", 0)
    __group = Group(__groupname, __ownername, None, __description, __genre)
    
    def test(self):
        """Tests insert of user, group, member, backup
        and select of group, members for group, groups for user, group details, all groups, groups for details, backup
        and deletion of backup."""
        
        # init DB
        PersistenceController.initPTPDatabase(schema='unittest')
        PersistenceController.cleanDatabase()
        
        # insert
#        self.__testInsertUsers()
#        self.__establishGroup()
#        self.__testInsertUserGroupAndGroup()
#        self.__testInsertMemberGroup()
#        self.__testInsertMessages()
#        
#        # select
#        self.__testSelectResponsibleUsersForUsername()
#        self.__testSelectUserGroup()
#        self.__testSelectGroupForGroupnameAndOwnername()
#        self.__testSelectGroupsForUsername()
#        self.__testSelectGroupsForDetails()
#        self.__testSelectAllGroups()
#        self.__testSelectGroupsWithMembersToConfirm()
#        self.__testSelectAndDeleteMessagesForUsername()
#        
#        # update
#        self.__testUpdateMemberGroup()
#        self.__testSelectGroupForGroupnameAndOwnername()
#        
#        self.__testSetIsActiveGroupForGroupnameAndOwnername()
#        self.__testSelectGroupForGroupnameAndOwnername()
#        
#        # backup
#        self.__testBackup()
#        self.__testSelectBackupFromUsers()
        
        #chathistory
        self.__testChatHistory()


    ##########
    # BACKUP #
    ##########
    
    def __testBackup(self):
        # check own backup
        print "--> __testBackup: check own backup"
        myBackup = PersistenceController.selectBackup(None)
        self.__checkBackup(myBackup)
        
        # delete own backup
        print "--> __testBackup: delete own backup"
        deleteBackup = BackupContent(None, None, None, None, PTPModel.BackupType.DELETE_ALL)
        isDeleted = PersistenceController.processBackup(deleteBackup, True)
        self.assertEqual(isDeleted, True)
        
        # check if own backup == None
        print "--> __testBackup: check if own backup==None"
        noneBackup = PersistenceController.selectBackup(None)
        self.assertEqual(noneBackup.getFromUsername(), None)
        self.assertEqual(noneBackup.getUsers(), None)
        self.assertEqual(noneBackup.getUserGroups(), None)
        self.assertEqual(noneBackup.getGroups(), None)
        
        # insert own backup
        print "--> __testBackup: insert again own backup"
        myBackup.setType(PTPModel.BackupType.UPDATE)
        isInserted = PersistenceController.processBackup(myBackup, True)
        self.assertEqual(isInserted, True)
        
        # check own backup
        print "--> __testBackup: check own backup again"
        myBackup = PersistenceController.selectBackup(None)
        self.__checkBackup(myBackup)
        
    def __testSelectBackupFromUsers(self):
        print "--> __testSelectBackupFromUsers"
        users = PersistenceController.selectBackupFromUsers()
        self.assertEqual(len(users), 0)

        
    ############
    # INSERTS ##
    ############
    
    def __testInsertUsers(self):
        print "--> __testInsertUsers: insert users:"
        print "    " + self.__user1.toString()
        print "    " + self.__user2.toString()
        isInserted = PersistenceController.insertUser(self.__user1)
        self.assertEqual(isInserted, True)
        isInserted = PersistenceController.insertUser(self.__user2)
        self.assertEqual(isInserted, True)
        
    def __establishGroup(self):
        print "--> __establishGroup: insert group:"
        print "    " + self.__group.toString()
        isInserted = PersistenceController.establishGroup(self.__group)
        self.assertEqual(isInserted, PTPModel.ReturnType.SUCCESSFUL)
        self.__group.addMember(self.__ownername, PTPModel.MemberStatus.ACTIVE, self.__timestamp)
        
    def __testInsertUserGroupAndGroup(self):
        print "--> __testInsertUserGroupAndGroup: insert user " + self.__membername + " into group " + self.__groupname + "(" + self.__ownername + ")"
        isInserted = PersistenceController.insertUserGroupAndGroup(self.__membername, self.__groupname, self.__ownername)
        self.assertEqual(isInserted, True)
        
    def __testInsertMemberGroup(self):
        print "--> __testInsertMemberGroup: insert member " + self.__membername + " into group " + self.__groupname + " (" + self.__ownername + ") with status " + self.__memberstatus
        isInserted = PersistenceController.insertMemberGroup(self.__membername, self.__groupname, self.__memberstatus, self.__timestamp, self.__ownername)
        self.assertEqual(isInserted, PTPModel.MemberStatusChangedReturnType.SUCCESSFUL)
        self.__group.addMember(self.__membername, PTPModel.MemberStatus.NOT_CONFIRMED)
    
    def __testInsertMessages(self):
        print "--> __testInsertMessages: insert messages sendMessage and memberStatusChangedMessage for user " + self.__username1
#        isInserted = PersistenceController.insertMessages(self.__username1, [self.__sendMessage, self.__memberStatusChangedMessage])
        isInserted = PersistenceController.insertMessages(self.__username1, [self.__memberStatusChangedMessage])
        self.assertEqual(isInserted, True)
#        self.__user1.setMessages([self.__sendMessage, self.__memberStatusChangedMessage])
        self.__user1.setMessages([self.__memberStatusChangedMessage])
        
        
    ###########
    # UPDATES #
    ###########
        
    def __testUpdateMemberGroup(self):
        print "--> __testUpdateMemberGroup: update memberstatus of " + self.__membername + " in group " + self.__groupname + " (" + self.__ownername + ") to " + PTPModel.MemberStatus.BLOCKED
        self.__group.setMemberStatus(self.__membername, PTPModel.MemberStatus.BLOCKED)
        isInserted = PersistenceController.updateMemberGroup(self.__membername, self.__groupname, self.__ownername, PTPModel.MemberStatus.BLOCKED, self.__timestamp)
        self.assertEqual(isInserted, True)
        
    def __testSetIsActiveGroupForGroupnameAndOwnername(self):
        print "--> __testSetIsActiveGroupForGroupnameAndOwnername: update active flag of " + self.__groupname + " (" + self.__ownername + ") to False"
        self.__group.setStatus(False)
        isChanged = PersistenceController.setIsActiveGroupForGroupnameAndOwnername(self.__groupname, self.__ownername, False)
        self.assertEqual(isChanged, True)
        
        
    ###########
    # SELECTS #
    ###########
    
    def __testSelectResponsibleUsersForUsername(self):
        print "--> __testSelectResponsibleUsersForUsername: select users I am responsible of for username " + self.__username1 + " and " + self.__username2
        user = PersistenceController.selectUserImResponsibleForUsername(self.__username1)
        self.__checkUser(user, self.__username1)
        self.__checkMessages(user.getMessages(), 2)
        user = PersistenceController.selectUserImResponsibleForUsername(self.__username2)
        self.__checkUser(user, self.__username2)
        self.__checkMessages(user.getMessages(), 0)
        
    def __testSelectUserGroup(self):
        print "--> __testSelectUserGroup: select user " + self.__username1 + " in group " + self.__groupname + " (" + self.__ownername + ")"
        userGroup = PersistenceController.selectUserGroup(self.__username1, self.__groupname, self.__ownername)
        self.assertEqual(userGroup.getGroupname(), self.__groupname)
        self.assertEqual(userGroup.getOwnername(), self.__ownername)
        self.assertEqual(userGroup.getUsername(), self.__username1)
    
    def __testSelectGroupForGroupnameAndOwnername(self):
        print "--> __testSelectGroupForGroupnameAndOwnername: select group " + self.__groupname + " (" + self.__ownername + ")"
        group = PersistenceController.selectGroupForGroupnameAndOwnername(self.__groupname, self.__ownername)
        self.__checkGroup(group)
        
    def __testSelectGroupsForUsername(self):
        print "--> __testSelectGroupsForUsername: select group for user " + self.__username1
        groups = PersistenceController.selectGroupsForUsername(self.__username1)
        self.assertEqual(len(groups), 1)
        self.__checkGroup(groups[0])
    
    def __testSelectGroupsForDetails(self):
        print "--> __testSelectGroupsForDetails: select group for detail description=" + self.__description + " and genre=" + self.__genre
        details = {"description" : self.__description, "genre" : self.__genre}
        groups = PersistenceController.selectGroupsForDetails(details)
        self.assertEqual(len(groups), 1)
        self.__checkGroup(groups[0])

    def __testSelectAllGroups(self):
        print "--> __testSelectAllGroups"
        groups = PersistenceController.selectAllGroups()
        self.assertEqual(len(groups), 1)
        self.assertEqual(groups[0].getGroupname(), self.__groupname)
        self.assertEqual(groups[0].getOwnername(), self.__ownername)
    
#    def __testSelectGroupsWithMembersToConfirm(self):
#        print "--> __testSelectGroupsWithMembersToConfirm: select groups of " + self.__ownername
#        groups = PersistenceController.selectGroupsWithMembersToConfirm(self.__ownername)
#        self.assertEqual(len(groups), 1)
#        self.assertEqual(groups[0].getGroupname(), self.__groupname)
#        self.assertEqual(groups[0].getOwnername(), self.__ownername)
#        self.assertEqual(groups[0].getGenre(), self.__genre)
#        self.assertEqual(groups[0].getDescription(), self.__description)
#        self.assertEqual(groups[0].isActive(), True)
#        members = groups[0].getMembers()
#        self.assertEqual(len(members), 1)
#        self.assertEqual(members.get(self.__membername), PTPModel.MemberStatus.NOT_CONFIRMED)
        
    def __testSelectAndDeleteMessagesForUsername(self):
        print "--> __testSelectAndDeleteMessagesForUsername: select messages for user " + self.__username1
        messages = PersistenceController.selectMessagesForUsername(self.__username1, False)
        self.__checkMessages(messages, 2)
        messages = PersistenceController.selectMessagesForUsername(self.__username1, True)
        self.__checkMessages(messages, 2)
        messages = PersistenceController.selectMessagesForUsername(self.__username1, False)
        self.__checkMessages(messages, 0)
        
        self.__user1.setMessages(None)
    
    
            
    ###########
    # HELPERS #
    ###########
    
    def __checkBackup(self, backup):
        self.assertEqual(backup.getFromUsername(), None)
        contains = backup.containsUser(self.__user1)
        self.assertEqual(contains, True)
        contains = backup.containsUser(self.__user2)
        self.assertEqual(contains, True)
        contains = backup.containsGroup(self.__group)
        self.assertEqual(contains, True)
        contains = backup.containsMemberGroup(self.__membername, self.__groupname)
        self.assertEqual(contains, True)
        contains = backup.containsMemberGroup(self.__ownername, self.__groupname)
        self.assertEqual(contains, True)
        userGroup = UserGroup(self.__membername, self.__groupname, self.__ownername)
        contains = backup.containsUserGroup(userGroup)
        self.assertEqual(contains, True)
        userGroup = UserGroup(self.__ownername, self.__groupname, self.__ownername)
        contains = backup.containsUserGroup(userGroup)
        self.assertEqual(contains, True)
            
    def __checkUser(self, user, username):
        self.assertEqual(user.getUsername(), username)
        self.assertEqual(user.getDisplayname(), username)
        self.assertEqual(user.getPassword(), self.__pw)
        self.assertEqual(user.getBackupFromUsername(), None)
            
    def __checkGroup(self, group):
        self.assertEqual(group.getGroupname(), self.__group.getGroupname())
        self.assertEqual(group.getDisplayname(), self.__group.getDisplayname())
        self.assertEqual(group.getOwnername(), self.__group.getOwnername())
        self.assertEqual(group.getGenre(), self.__group.getGenre())
        self.assertEqual(group.getDescription(), self.__group.getDescription())
        self.assertEqual(group.isActive(), self.__group.isActive())
        self.assertEqual(len(group.getMembers()), len(self.__group.getMembers()))
        self.assertEqual(group.containsMember(self.__ownername), self.__group.containsMember(self.__ownername))
        self.assertEqual(group.containsMember(self.__membername), self.__group.containsMember(self.__membername))
        self.assertEqual(group.getMembers().get(self.__ownername), self.__group.getMembers().get(self.__ownername))
        self.assertEqual(group.getMembers().get(self.__membername), self.__group.getMembers().get(self.__membername))
    
    def __checkMessages(self, messages, nrOfMsg):
        if messages == None:
            self.assertEqual(0, nrOfMsg)
        else:
            self.assertEqual(len(messages), nrOfMsg)
            if nrOfMsg == 1:
#                if messages[0].getQueueType() == CustodyModel.CustodyQueueType.MEMBER_STATUS_CHANGED:
                isEqual = CustodyModel.isEqual(messages[0], self.__memberStatusChangedMessage)
                self.assertEqual(isEqual, True)
#                    isEqual = CustodyModel.isEqual(messages[1], self.__sendMessage)
#                    self.assertEqual(isEqual, True)
#                else:
#                    isEqual = CustodyModel.isEqual(messages[0], self.__sendMessage)
#                    self.assertEqual(isEqual, True)
#                    isEqual = CustodyModel.isEqual(messages[1], self.__memberStatusChangedMessage)
#                    self.assertEqual(isEqual, True)
                    
    ##################
    ## CHAT HISTORY ##
    ##################
    def __testChatHistory(self):
        senderName = "testSender"
        username = "testSender"
        partnername = "testReceiver"
        message = "message"
        timestamp = time.time()
        status = PTPModel.ChatMessageStatus.SENDING
        chatMessage = PTPModel.ChatMessage(senderName, message, timestamp, status)
        PersistenceController.insertChatMessage(username, partnername, chatMessage)
        PersistenceController.updateChatMessageForSendernameAndTimestamp(senderName, timestamp, PTPModel.ChatMessageStatus.SENT)
        messages = PersistenceController.selectChatHistoryByPartnernameAndUsername(partnername, username)
        self.assertEqual(1, len(messages))
    
def suite():
    suite = unittest.TestSuite()
    suite.addTest(unittest.makeSuite(PTPTest))
    return suite

if __name__ == '__main__':
    suiteFew = unittest.TestSuite()
    unittest.TextTestRunner(verbosity=2).run(suite())
